//#include <stdio.h>
//#include <stdlib.h>
//#include <unistd.h>
#include "drne_list.h"


//#include "istdafx.h"
//#include "sstdafx.h"

/**/
#define DRNE_TIMER_CHECK	3	// 3 seconds

int time_cmp_sec( time_t start, time_t stop, unsigned int sec_val )
{
	unsigned int   sec;

	if( stop < start )
		return 1;

	sec	=  stop - start;

	return (sec > sec_val);
}


/**/
drne_list::drne_list( int max ) : m_max( max )
{
	m_age		= DRNE_TIMER_AGE;
	time( &m_timer );
}

drne_list::~drne_list(void)
{
	free( );
}

void drne_list::free(void)
{
	m_lst.free(1);			// free memory and point to NULL
}

void drne_list::tick(void)
{
	int						i;
	int						flag;
	time_t					cur_tm;
	list_node<t_drne_net>	* pnode	= NULL;
	list_node<t_drne_net>	* ptemp;
	int						s_info;

	// syn timer
	time( &cur_tm );
	if( time_cmp_sec( m_timer, cur_tm, DRNE_TIMER_CHECK ) == 0 )
	{
		return; 
	}
	m_timer			= cur_tm;

	// find list head
	pnode			= m_lst.next( pnode );

	s_info			= 0;

	while( pnode != NULL )
	{
		ptemp		= pnode;

		flag		= 1;
		for( i = 0; i < DRNE_MAX_SN_NODE_NUM; ++i )
		{
			if( pnode->data.inf[i].used )
			{
				if( time_cmp_sec( pnode->data.inf[i].timer, cur_tm, m_age ) )
				{
					pnode->data.inf[i].used	= 0;
//					flag	= 1;
					s_info	= 1;
				}
				else
				{
					flag	= 0;
				}
			}
		}
		pnode	= m_lst.next( pnode );

		if( flag )
		{
			m_lst.remove( ptemp );
			delete ptemp;

			s_info	= 1;
		}
	}

	if( s_info )
	{
		show( );
	}
}

int drne_list::insert( unsigned int addr, unsigned int port, unsigned short frmno )
{
	unsigned char			node	= (unsigned char)addr;
	list_node<t_drne_net>	* pnode	= NULL;

	pnode	= get( addr );
	if( pnode == NULL )
	{
		if( m_lst.get_len( ) >= m_max )
			return 0;

		pnode	= new list_node<t_drne_net>;

		for( int j = 0; j < DRNE_MAX_SN_NODE_NUM; ++j )
		{
			pnode->data.inf[j].used		= 0;
		}
		//
		pnode->data.subnet				= addr & 0xFFFFFF00;
		pnode->data.inf[node].used		= 1;
		pnode->data.inf[node].port		= port;
		pnode->data.inf[node].frmno		= frmno;
		time( &(pnode->data.inf[node].timer) );

		m_lst.append( pnode );
	}
	else
	{
		if( pnode->data.inf[node].used )
		{
			if( pnode->data.inf[node].frmno == frmno )
			{
				return 0;
			}
			else if( pnode->data.inf[node].frmno < frmno )
			{
				if( frmno - pnode->data.inf[node].frmno > DRNE_FRMNO_LIMIT )
				{
					return 0;
				}
			}
			else
			{
				if( 0xFFFF - pnode->data.inf[node].frmno + frmno > DRNE_FRMNO_LIMIT )
				{
					return 0;
				}
			}
		}

		pnode->data.inf[node].used		= 1;
		pnode->data.inf[node].port		= port;
		pnode->data.inf[node].frmno		= frmno;
		time( &(pnode->data.inf[node].timer) );
	}

	show( );

	return 1;
}

list_node<t_drne_net> * drne_list::get( unsigned int addr )
{
	unsigned int			subnet	= addr & 0xFFFFFF00;
	list_node<t_drne_net>	* pnode	= NULL;

	// find list head
	pnode			= m_lst.next( pnode );

	while( pnode != NULL )
	{
		if( pnode->data.subnet == subnet )
			return pnode;

		pnode		= m_lst.next( pnode );
	}

	return NULL;
}

unsigned int drne_list::dstport( unsigned int addr )
{
	list_node<t_drne_net>	* pnode	= NULL;
	unsigned char			pos;

	pnode		= get( addr );
	if( pnode != NULL )
	{
		pos		= (unsigned char)addr;
		if( pnode->data.inf[pos].used )
		{
			return pnode->data.inf[pos].port;
		}
	}

	return 0xFFFFFFFF;
}

void drne_list::remove( unsigned int addr )
{
	list_node<t_drne_net>	* pnode	= NULL;

	pnode	= get( addr );
	if( pnode != NULL )
	{
		m_lst.remove( pnode );
		delete pnode;
	}
}

void drne_list::show( void )
{
#ifdef DRNE_DEBUG_EN
	list_node<t_drne_net>	* pnode	= NULL;

	DPRINT(( "\n======================== list ==========================\n" ));
	pnode			= m_lst.next( pnode );
	while( pnode != NULL )
	{
		DPRINT("%08x[%d.%d.%d.0] : \n"	, (unsigned int )(pnode->data.subnet)
										, (unsigned char)(pnode->data.subnet >> 24)
										, (unsigned char)(pnode->data.subnet >> 16)
										, (unsigned char)(pnode->data.subnet >>  8) );
		for(int j = 0; j < DRNE_MAX_SN_NODE_NUM; ++j)
		{
			if( pnode->data.inf[j].used )
			{
				DPRINT( "\t[%02x, %08x, %04x, %08x]\n", j, (int)pnode->data.inf[j].port, pnode->data.inf[j].frmno, (int)pnode->data.inf[j].timer );
			}
		}
		DPRINT(("\n"));

		pnode		= m_lst.next( pnode );
	}
	DPRINT(( "========================================================\n\n" ));
#endif
}
